/* eslint-disable */
var __extends =
    (this && this.__extends) ||
    (function () {
        var extendStatics = function (d, b) {
            extendStatics =
                Object.setPrototypeOf ||
                ({
                    __proto__: []
                } instanceof Array &&
                    function (d, b) {
                        d.__proto__ = b;
                    }) ||
                function (d, b) {
                    for (var p in b) {
                        if (Object.prototype.hasOwnProperty.call(b, p)) {
                            d[p] = b[p];
                        }
                    }
                };

            return extendStatics(d, b);
        };

        return function (d, b) {
            if (typeof b !== 'function' && b !== null) {
                throw new TypeError('Class extends value ' + String(b) + ' is not a constructor or null');
            }

            extendStatics(d, b);

            function __() {
                this.constructor = d;
            }

            if (b === null) {
                d.prototype = Object.create(b);
            } else {
                d.prototype = ((__.prototype = b.prototype), new __());
            }
        };
    })();

import { hex2b64 } from './lib/jsbn/base64';
import { Hex } from './lib/asn1js/hex';
import { Base64 } from './lib/asn1js/base64';
import { ASN1 } from './lib/asn1js/asn1';
import { RSAKey } from './lib/jsbn/rsa';
import { parseBigInt } from './lib/jsbn/jsbn';
import { KJUR } from './lib/jsrsasign/asn1-1.0';
/**
 * Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object.
 * This object is just a decorator for parsing the key parameter
 * @param {string|Object} key - The key in string format, or an object containing
 * the parameters needed to build a RSAKey object.
 * @constructor
 */

var JSEncryptRSAKey =
    /** @class */
    (function (_super) {
        __extends(JSEncryptRSAKey, _super);

        function JSEncryptRSAKey(key) {
            var _this = _super.call(this) || this; // Call the super constructor.
            //  RSAKey.call(this);
            // If a key key was provided.

            if (key) {
                // If this is a string...
                if (typeof key === 'string') {
                    _this.parseKey(key);
                } else {
                    if (JSEncryptRSAKey.hasPrivateKeyProperty(key) || JSEncryptRSAKey.hasPublicKeyProperty(key)) {
                        // Set the values for the key.
                        _this.parsePropertiesFrom(key);
                    }
                }
            }

            return _this;
        }
        /**
         * Method to parse a pem encoded string containing both a public or private key.
         * The method will translate the pem encoded string in a der encoded string and
         * will parse private key and public key parameters. This method accepts public key
         * in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1).
         *
         * @todo Check how many rsa formats use the same format of pkcs #1.
         *
         * The format is defined as:
         * PublicKeyInfo ::= SEQUENCE {
         *   algorithm       AlgorithmIdentifier,
         *   PublicKey       BIT STRING
         * }
         * Where AlgorithmIdentifier is:
         * AlgorithmIdentifier ::= SEQUENCE {
         *   algorithm       OBJECT IDENTIFIER,     the OID of the enc algorithm
         *   parameters      ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
         * }
         * and PublicKey is a SEQUENCE encapsulated in a BIT STRING
         * RSAPublicKey ::= SEQUENCE {
         *   modulus           INTEGER,  -- n
         *   publicExponent    INTEGER   -- e
         * }
         * it's possible to examine the structure of the keys obtained from openssl using
         * an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/
         * @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer
         * @private
         */

        JSEncryptRSAKey.prototype.parseKey = function (pem) {
            try {
                var modulus = 0;
                var public_exponent = 0;
                var reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/;
                var der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem);
                var asn1 = ASN1.decode(der); // Fixes a bug with OpenSSL 1.0+ private keys

                if (asn1.sub.length === 3) {
                    asn1 = asn1.sub[2].sub[0];
                }

                if (asn1.sub.length === 9) {
                    // Parse the private key.
                    modulus = asn1.sub[1].getHexStringValue(); // bigint

                    this.n = parseBigInt(modulus, 16);
                    public_exponent = asn1.sub[2].getHexStringValue(); // int

                    this.e = parseInt(public_exponent, 16);
                    var private_exponent = asn1.sub[3].getHexStringValue(); // bigint

                    this.d = parseBigInt(private_exponent, 16);
                    var prime1 = asn1.sub[4].getHexStringValue(); // bigint

                    this.p = parseBigInt(prime1, 16);
                    var prime2 = asn1.sub[5].getHexStringValue(); // bigint

                    this.q = parseBigInt(prime2, 16);
                    var exponent1 = asn1.sub[6].getHexStringValue(); // bigint

                    this.dmp1 = parseBigInt(exponent1, 16);
                    var exponent2 = asn1.sub[7].getHexStringValue(); // bigint

                    this.dmq1 = parseBigInt(exponent2, 16);
                    var coefficient = asn1.sub[8].getHexStringValue(); // bigint

                    this.coeff = parseBigInt(coefficient, 16);
                } else {
                    if (asn1.sub.length === 2) {
                        // Parse the public key.
                        var bit_string = asn1.sub[1];
                        var sequence = bit_string.sub[0];
                        modulus = sequence.sub[0].getHexStringValue();
                        this.n = parseBigInt(modulus, 16);
                        public_exponent = sequence.sub[1].getHexStringValue();
                        this.e = parseInt(public_exponent, 16);
                    } else {
                        return false;
                    }
                }

                return true;
            } catch (ex) {
                return false;
            }
        };
        /**
         * Translate rsa parameters in a hex encoded string representing the rsa key.
         *
         * The translation follow the ASN.1 notation :
         * RSAPrivateKey ::= SEQUENCE {
         *   version           Version,
         *   modulus           INTEGER,  -- n
         *   publicExponent    INTEGER,  -- e
         *   privateExponent   INTEGER,  -- d
         *   prime1            INTEGER,  -- p
         *   prime2            INTEGER,  -- q
         *   exponent1         INTEGER,  -- d mod (p1)
         *   exponent2         INTEGER,  -- d mod (q-1)
         *   coefficient       INTEGER,  -- (inverse of q) mod p
         * }
         * @returns {string}  DER Encoded String representing the rsa private key
         * @private
         */

        JSEncryptRSAKey.prototype.getPrivateBaseKey = function () {
            var options = {
                array: [
                    new KJUR.asn1.DERInteger({
                        int: 0
                    }),
                    new KJUR.asn1.DERInteger({
                        bigint: this.n
                    }),
                    new KJUR.asn1.DERInteger({
                        int: this.e
                    }),
                    new KJUR.asn1.DERInteger({
                        bigint: this.d
                    }),
                    new KJUR.asn1.DERInteger({
                        bigint: this.p
                    }),
                    new KJUR.asn1.DERInteger({
                        bigint: this.q
                    }),
                    new KJUR.asn1.DERInteger({
                        bigint: this.dmp1
                    }),
                    new KJUR.asn1.DERInteger({
                        bigint: this.dmq1
                    }),
                    new KJUR.asn1.DERInteger({
                        bigint: this.coeff
                    })
                ]
            };
            var seq = new KJUR.asn1.DERSequence(options);
            return seq.getEncodedHex();
        };
        /**
         * base64 (pem) encoded version of the DER encoded representation
         * @returns {string} pem encoded representation without header and footer
         * @public
         */

        JSEncryptRSAKey.prototype.getPrivateBaseKeyB64 = function () {
            return hex2b64(this.getPrivateBaseKey());
        };
        /**
         * Translate rsa parameters in a hex encoded string representing the rsa public key.
         * The representation follow the ASN.1 notation :
         * PublicKeyInfo ::= SEQUENCE {
         *   algorithm       AlgorithmIdentifier,
         *   PublicKey       BIT STRING
         * }
         * Where AlgorithmIdentifier is:
         * AlgorithmIdentifier ::= SEQUENCE {
         *   algorithm       OBJECT IDENTIFIER,     the OID of the enc algorithm
         *   parameters      ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
         * }
         * and PublicKey is a SEQUENCE encapsulated in a BIT STRING
         * RSAPublicKey ::= SEQUENCE {
         *   modulus           INTEGER,  -- n
         *   publicExponent    INTEGER   -- e
         * }
         * @returns {string} DER Encoded String representing the rsa public key
         * @private
         */

        JSEncryptRSAKey.prototype.getPublicBaseKey = function () {
            var first_sequence = new KJUR.asn1.DERSequence({
                array: [
                    new KJUR.asn1.DERObjectIdentifier({
                        oid: '1.2.840.113549.1.1.1'
                    }),
                    new KJUR.asn1.DERNull()
                ]
            });
            var second_sequence = new KJUR.asn1.DERSequence({
                array: [
                    new KJUR.asn1.DERInteger({
                        bigint: this.n
                    }),
                    new KJUR.asn1.DERInteger({
                        int: this.e
                    })
                ]
            });
            var bit_string = new KJUR.asn1.DERBitString({
                hex: '00' + second_sequence.getEncodedHex()
            });
            var seq = new KJUR.asn1.DERSequence({
                array: [first_sequence, bit_string]
            });
            return seq.getEncodedHex();
        };
        /**
         * base64 (pem) encoded version of the DER encoded representation
         * @returns {string} pem encoded representation without header and footer
         * @public
         */

        JSEncryptRSAKey.prototype.getPublicBaseKeyB64 = function () {
            return hex2b64(this.getPublicBaseKey());
        };
        /**
         * wrap the string in block of width chars. The default value for rsa keys is 64
         * characters.
         * @param {string} str the pem encoded string without header and footer
         * @param {Number} [width=64] - the length the string has to be wrapped at
         * @returns {string}
         * @private
         */

        JSEncryptRSAKey.wordwrap = function (str, width) {
            width = width || 64;

            if (!str) {
                return str;
            }

            var regex = '(.{1,' + width + '})( +|$\n?)|(.{1,' + width + '})';
            return str.match(RegExp(regex, 'g')).join('\n');
        };
        /**
         * Retrieve the pem encoded private key
         * @returns {string} the pem encoded private key with header/footer
         * @public
         */

        JSEncryptRSAKey.prototype.getPrivateKey = function () {
            var key = '-----BEGIN RSA PRIVATE KEY-----\n';
            key += JSEncryptRSAKey.wordwrap(this.getPrivateBaseKeyB64()) + '\n';
            key += '-----END RSA PRIVATE KEY-----';
            return key;
        };
        /**
         * Retrieve the pem encoded public key
         * @returns {string} the pem encoded public key with header/footer
         * @public
         */

        JSEncryptRSAKey.prototype.getPublicKey = function () {
            var key = '-----BEGIN PUBLIC KEY-----\n';
            key += JSEncryptRSAKey.wordwrap(this.getPublicBaseKeyB64()) + '\n';
            key += '-----END PUBLIC KEY-----';
            return key;
        };
        /**
         * Check if the object contains the necessary parameters to populate the rsa modulus
         * and public exponent parameters.
         * @param {Object} [obj={}] - An object that may contain the two public key
         * parameters
         * @returns {boolean} true if the object contains both the modulus and the public exponent
         * properties (n and e)
         * @todo check for types of n and e. N should be a parseable bigInt object, E should
         * be a parseable integer number
         * @private
         */

        JSEncryptRSAKey.hasPublicKeyProperty = function (obj) {
            obj = obj || {};
            return obj.hasOwnProperty('n') && obj.hasOwnProperty('e');
        };
        /**
         * Check if the object contains ALL the parameters of an RSA key.
         * @param {Object} [obj={}] - An object that may contain nine rsa key
         * parameters
         * @returns {boolean} true if the object contains all the parameters needed
         * @todo check for types of the parameters all the parameters but the public exponent
         * should be parseable bigint objects, the public exponent should be a parseable integer number
         * @private
         */

        JSEncryptRSAKey.hasPrivateKeyProperty = function (obj) {
            obj = obj || {};
            return (
                obj.hasOwnProperty('n') &&
                obj.hasOwnProperty('e') &&
                obj.hasOwnProperty('d') &&
                obj.hasOwnProperty('p') &&
                obj.hasOwnProperty('q') &&
                obj.hasOwnProperty('dmp1') &&
                obj.hasOwnProperty('dmq1') &&
                obj.hasOwnProperty('coeff')
            );
        };
        /**
         * Parse the properties of obj in the current rsa object. Obj should AT LEAST
         * include the modulus and public exponent (n, e) parameters.
         * @param {Object} obj - the object containing rsa parameters
         * @private
         */

        JSEncryptRSAKey.prototype.parsePropertiesFrom = function (obj) {
            this.n = obj.n;
            this.e = obj.e;

            if (obj.hasOwnProperty('d')) {
                this.d = obj.d;
                this.p = obj.p;
                this.q = obj.q;
                this.dmp1 = obj.dmp1;
                this.dmq1 = obj.dmq1;
                this.coeff = obj.coeff;
            }
        };

        return JSEncryptRSAKey;
    })(RSAKey);

export { JSEncryptRSAKey };
